package com.linq.cool.beauty.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linq.cool.api.domain.BeautyMember;
import com.linq.cool.beauty.domain.*;
import com.linq.cool.beauty.dto.BeautyOrderDTO;
import com.linq.cool.beauty.dto.BeautyOrderQueryDTO;
import com.linq.cool.beauty.enums.OrderStateEnum;
import com.linq.cool.beauty.mapper.BeautyOrderMapper;
import com.linq.cool.beauty.service.*;
import com.linq.cool.beauty.vo.statistical.StatisticalVO;
import com.linq.cool.common.constants.Constants;
import com.linq.cool.common.constants.UserConstants;
import com.linq.cool.common.core.exception.BusinessException;
import com.linq.cool.common.core.utils.IdWorker;
import com.linq.cool.common.core.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: yqlin
 * @Date: 2021/2/11 00:34
 * @Description:
 * @Version: 1.0.0
 */

@Service
public class BeautyOrderServiceImpl extends ServiceImpl<BeautyOrderMapper, BeautyOrder> implements BeautyOrderService {
    @Autowired
    private BeautyProductService beautyProductService;
    @Autowired
    private BeautyCouponService beautyCouponService;
    @Autowired
    private BeautyOrderItemService beautyOrderItemService;
    @Autowired
    private BeautyOrderHistoryService beautyOrderHistoryService;
    @Autowired
    private BeautyCouponHistoryService beautyCouponHistoryService;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    private BeautyMemberService beautyMemberService;
    @Autowired
    private BeautyServiceStoreService serviceStoreService;
    @Autowired
    private BeautyCartItemService cartItemService;
    @Autowired
    private BeautyOrderPayService orderPayService;
    @Autowired
    private BeautyProductStatisticalService productStatisticalService;

    /**
     * 1. 前端提交订单参数：商品编号、优惠券编号等
     * 2. 计算总金额，如果用了优惠券就扣除优惠券的金额
     * 3. 存入订单表、订单项表、订单历史表
     * 4. 清除购物车
     * 4. 优惠券状态变更为已使用
     *
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long createOrder(BeautyOrderDTO dto) {
        List<Long> productIds = dto.getProductIds();
        // 根据商品ids查询所有商品
        List<BeautyProduct> products = beautyProductService.listByIds(productIds);
        //  2. 计算总金额，如果用了优惠券就扣除优惠券的金额
        BigDecimal totalMoney = BigDecimal.ZERO;
        // 获得的积分
        BigDecimal totalPoint = BigDecimal.ZERO;
        // 先算商品价格
        for (BeautyProduct product : products) {
            totalMoney = totalMoney.add(product.getPrice());
            if (null != product.getPoint()) {
                totalPoint = totalPoint.add(product.getPoint());
            }
        }
        // 应付金额
        BigDecimal payAmount = BigDecimal.ZERO;
        // 优惠券金额
        BigDecimal couponAmount = BigDecimal.ZERO;
        if (dto.getCouponId() != null) {
            // 拿到优惠券
            BeautyCoupon coupon = beautyCouponService.getById(dto.getCouponId());
            if (coupon != null) {
                couponAmount = coupon.getAmount();
                payAmount = totalMoney.subtract(coupon.getAmount());
            }
        } else {
            // 没有优惠券 应付金额 和 总金额一样
            payAmount = totalMoney;
        }
        // 存入订单表、订单项表、订单历史表
        // 查询当前客户
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        // 查询服务店面信息
        BeautyServiceStore serviceStore = serviceStoreService.getById(dto.getServiceStoreId());
        if (null == serviceStore) {
            throw new BusinessException("该店面不存在");
        }
        BeautyOrder order = new BeautyOrder();
        order.setId(idWorker.nextId())
                .setProvince(serviceStore.getProvince())
                .setCity(serviceStore.getCity())
                .setCounty(serviceStore.getCounty())
                .setMemberId(member.getId())
                .setTotalAmount(totalMoney)
                .setPayAmount(payAmount)
                .setCouponAmount(couponAmount)
                .setIntegration(totalPoint)
                .setRemark(dto.getRemark())
                .setServiceStoreId(serviceStore.getId())
                .setServiceStoreName(serviceStore.getName())
                .setStatus(OrderStateEnum.WAIT_PAY.getCode())
        ;
        // 历史订单
        BeautyOrderHistory orderHistory = new BeautyOrderHistory();
        orderHistory.setId(idWorker.nextId())
                .setMemberId(member.getId())
                .setMemberPhone(member.getPhone())
                .setMemberRealName(member.getRealName())
                .setRemark(order.getRemark())
                .setOrderId(order.getId())
                // 代付款
                .setOrderStatus(OrderStateEnum.WAIT_PAY.getCode());
        // 构造订单项目
        List<BeautyOrderItem> orderItems = products.stream().map(p -> {
            BeautyOrderItem orderItem = new BeautyOrderItem();
            orderItem.setId(idWorker.nextId())
                    .setOrderId(order.getId())
                    .setIntegration(p.getPoint())
                    .setProductId(p.getId())
                    .setProductName(p.getName())
                    .setProductPic(p.getPic())
                    .setProductCategoryId(p.getProductCategoryId())
                    .setProductPrice(p.getPrice())
                    .setBrandId(p.getBrandId())
                    .setBrandName(p.getBrandName())
                    .setServiceStoreId(serviceStore.getId())
                    .setServiceStoreName(serviceStore.getName())
            ;
            return orderItem;
        }).collect(Collectors.toList());
        beautyOrderHistoryService.save(orderHistory);
        this.save(order);
        beautyOrderItemService.saveBatch(orderItems);
        // 清除购物车
        // 查询当前客户的购物车
        List<BeautyCartItem> cartItems = cartItemService.list(new LambdaQueryWrapper<BeautyCartItem>()
                                                                      .in(BeautyCartItem::getProductId, productIds)
                                                                      .eq(BeautyCartItem::getMemberId, SecurityUtils.getUserId())
                                                                      .eq(BeautyCartItem::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        );
        if (CollectionUtils.isNotEmpty(cartItems)) {
            List<Long> cartItemsIds = cartItems.stream().map(BeautyCartItem::getId).collect(Collectors.toList());
            cartItemService.removeByIds(cartItemsIds);
        }
        // TOOD 优惠券状态变更为已使用
        if (null != dto.getCouponId()) {
            // 更新优惠券使用数量
            BeautyCoupon coupon = beautyCouponService.getById(dto.getCouponId());
            coupon.setUseCount(coupon.getUseCount() + 1);
            beautyCouponService.updateById(coupon);
            // 优惠券领取历史表数据状态变更为已使用，更新使用时间和订单号
            BeautyCouponHistory couponHistory = beautyCouponHistoryService.getOne(new LambdaQueryWrapper<BeautyCouponHistory>()
                                                                                          .eq(BeautyCouponHistory::getCouponId, coupon.getId())
                                                                                          .eq(BeautyCouponHistory::getMemberId, SecurityUtils.getUserId())
            );
            // 默认就是未使用
            couponHistory.setUseTime(new Date()).setOrderId(order.getId());
            beautyCouponHistoryService.updateById(couponHistory);
        }
        // 统计下单数 更新
        dto.getProductIds().forEach(id -> {
            BeautyProductStatistical one = productStatisticalService.getOne(new LambdaQueryWrapper<BeautyProductStatistical>()
                                                                                    .eq(BeautyProductStatistical::getProductId, id)
            );
            if (null == one) {
                productStatisticalService.save(new BeautyProductStatistical().setProductId(id).setOrderCount(1));
            } else {
                one.setOrderCount(one.getOrderCount() + 1);
                productStatisticalService.updateById(one);
            }
        });
        // 返回创建好的订单号
        return order.getId();
    }

    @Override
    public IPage<BeautyOrder> listByPage(IPage<BeautyOrder> page, BeautyOrderQueryDTO dto) {
        return this.page(page, this.getLambdaQueryWrapper(dto));
    }

    @Override
    public IPage<BeautyOrder> listMemberOrdersByPage(IPage<BeautyOrder> page, BeautyOrderQueryDTO dto) {
        return baseMapper.listMemberOrdersByPage(page, dto, SecurityUtils.getUserId());
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelMemberOrder(Long orderId) {
        // 查询当前客户的订单列表 判断 这个订单id是否可以被取消  订单必须是 待付款的才能取消
        BeautyOrder one = this.getOne(new LambdaQueryWrapper<BeautyOrder>()
                                              .eq(BeautyOrder::getMemberId, SecurityUtils.getUserId())
                                              .eq(BeautyOrder::getId, orderId)
                                              .eq(BeautyOrder::getStatus, OrderStateEnum.WAIT_PAY.getCode())
                                              .eq(BeautyOrder::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        );
        if (null == one) {
            throw new BusinessException("该订单是无效订单,无法取消");
        }
        one.setStatus(OrderStateEnum.INVALID.getCode());
        this.updateById(one);
        // 新增历史订单
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        BeautyOrderHistory orderHistory = new BeautyOrderHistory();
        orderHistory.setId(idWorker.nextId())
                .setMemberId(member.getId())
                .setMemberPhone(member.getPhone())
                .setMemberRealName(member.getRealName())
                .setOrderId(one.getId())
                .setRemark(one.getRemark())
                // 代付款
                .setOrderStatus(OrderStateEnum.INVALID.getCode());
        beautyOrderHistoryService.save(orderHistory);
    }

    @Override
    public List<BeautyOrderItem> getMemberOrderItems(Long orderId) {
        // 判断当前 订单号是否有效
        BeautyOrder one = this.getOne(new LambdaQueryWrapper<BeautyOrder>()
                                              .eq(BeautyOrder::getMemberId, SecurityUtils.getUserId())
                                              .eq(BeautyOrder::getId, orderId)
                                              .eq(BeautyOrder::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        );
        if (null == one) {
            throw new BusinessException("该订单不存在");
        }
        List<BeautyOrderItem> orderItems = beautyOrderItemService.list(new LambdaQueryWrapper<BeautyOrderItem>()
                                                                               .eq(BeautyOrderItem::getOrderId, orderId)
                                                                               .eq(BeautyOrderItem::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
        );
        if (CollectionUtils.isEmpty(orderItems)) {
            orderItems = new ArrayList<>(0);
        }
        return orderItems;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void confirmMemberOrderPay(Long orderId) {
        // 1.更细订单状态
        // 查询当前订单 信息
        BeautyOrder order = this.getById(orderId);
        if (null == order || !OrderStateEnum.WAIT_PAY.getCode().equals(order.getStatus())) {
            throw new BusinessException("该订单为无效订单");
        }
        order.setStatus(OrderStateEnum.WAIT_CONFIRM.getCode()).setPaymentTime(new Date());
        this.updateById(order);
        // 2.新增订单支付信息
        BeautyOrderPay orderPay = new BeautyOrderPay();
        orderPay.setId(idWorker.nextId())
                .setOrderId(order.getId())
                .setPayAmount(order.getPayAmount())
                .setStatus(OrderStateEnum.WAIT_CONFIRM.getCode())
                .setMemberId(SecurityUtils.getUserId())
        ;
        orderPayService.save(orderPay);
        //  更新用户相关信息 金额 积分
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        member.setAmount(member.getAmount().subtract(order.getPayAmount()))
                .setPoint(member.getPoint().add(order.getIntegration()))
                .setHistoryPoint(member.getPoint().add(order.getIntegration()))
                .setGmtModified(new Date());
        beautyMemberService.updateById(member);
        //  新增订单历史
        BeautyOrderHistory orderHistory = new BeautyOrderHistory();
        orderHistory.setId(idWorker.nextId())
                .setMemberId(member.getId())
                .setMemberPhone(member.getPhone())
                .setMemberRealName(member.getRealName())
                .setOrderId(order.getId())
                .setRemark(order.getRemark())
                // 代付款
                .setOrderStatus(OrderStateEnum.WAIT_CONFIRM.getCode());
        beautyOrderHistoryService.save(orderHistory);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void confirmMemberOrder(Long orderId) {
        BeautyOrder order = this.getOne(new LambdaQueryWrapper<BeautyOrder>()
                                                .eq(BeautyOrder::getId, orderId)
                                                .eq(BeautyOrder::getStatus, OrderStateEnum.WAIT_CONFIRM.getCode())
                                                .eq(BeautyOrder::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
                                                .eq(BeautyOrder::getMemberId, SecurityUtils.getUserId())
        );
        if (null == order) {
            throw new BusinessException("该订单无效");
        }
        order.setStatus(OrderStateEnum.ALREADY_SIGN.getCode()).setGmtModified(new Date());
        this.updateById(order);
        //  新增订单历史
        BeautyMember member = beautyMemberService.getById(SecurityUtils.getUserId());
        BeautyOrderHistory orderHistory = new BeautyOrderHistory();
        orderHistory.setId(idWorker.nextId())
                .setMemberId(member.getId())
                .setMemberPhone(member.getPhone())
                .setMemberRealName(member.getRealName())
                .setOrderId(order.getId())
                .setRemark(order.getRemark())
                // 待评价
                .setOrderStatus(OrderStateEnum.ALREADY_SIGN.getCode());
        beautyOrderHistoryService.save(orderHistory);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void autoConfirmMemberOrderFinish() {
        // 查询出所有状态为待评价的 订单
        List<BeautyOrder> orders = this.list(new LambdaQueryWrapper<BeautyOrder>()
                                                     .eq(BeautyOrder::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
                                                     .eq(BeautyOrder::getStatus, OrderStateEnum.ALREADY_SIGN.getCode())
        );
        if (CollectionUtils.isNotEmpty(orders)) {
            // 筛选出与当天时间大于天的--3天自动完成
            List<BeautyOrder> needFinishOrders = orders.stream().map(e -> {
                Calendar cal = Calendar.getInstance();
                cal.setTime(e.getGmtModified());
                long preDate = cal.getTimeInMillis();
                cal.setTime(new Date());
                long curDate = cal.getTimeInMillis();
                long betweenDays = (curDate - preDate) / (1000 * 3600 * 24);
                if (betweenDays >= UserConstants.AUTO_FININSH_DAYS) {
                    return e;
                } else {
                    return null;
                }
            }).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(needFinishOrders)) {
                // 批量更新订单的状态
                needFinishOrders.forEach(e -> {
                    e.setStatus(OrderStateEnum.FINISH.getCode());
                });
                this.updateBatchById(needFinishOrders);
                // 批量增加历史记录
                List<BeautyOrderHistory> orderHistoryList = needFinishOrders.stream().map(e -> {
                    BeautyOrderHistory orderHistory = new BeautyOrderHistory();
                    orderHistory.setId(idWorker.nextId())
                            .setMemberId(e.getMemberId())
                            .setOrderId(e.getId())
                            .setRemark(e.getRemark())
                            // 已经完成
                            .setOrderStatus(OrderStateEnum.FINISH.getCode());
                    return orderHistory;
                }).collect(Collectors.toList());
                beautyOrderHistoryService.saveBatch(orderHistoryList);
            }
        }

    }

    @Override
    public List<StatisticalVO> statisticMonthOrder() {
        List<StatisticalVO> list = baseMapper.statisticMonthOrder();
        if (CollectionUtils.isEmpty(list)) {
            StatisticalVO vo = new StatisticalVO();
            vo.setName("暂无").setValue("暂无").setExtra("暂无");
            list.add(vo);
        }
        return list;
    }

    @Override
    public List<StatisticalVO> statisticMemberMonthOrder(Long memberId) {
        List<StatisticalVO> list = baseMapper.statisticMemberMonthOrder(memberId);
        if (CollectionUtils.isEmpty(list)) {
            StatisticalVO vo = new StatisticalVO();
            vo.setName("暂无").setValue("暂无").setExtra("暂无");
            list.add(vo);
        }
        return list;
    }

    private LambdaQueryWrapper<BeautyOrder> getLambdaQueryWrapper(BeautyOrderQueryDTO dto) {
        return new LambdaQueryWrapper<BeautyOrder>()
                .eq(BeautyOrder::getIsDeleted, UserConstants.StateEnum.DELETE_FLAG_EXIST.getCode())
                .orderByDesc(BeautyOrder::getGmtCreate)
                .eq(StringUtils.checkValNotNull(dto.getStatus()), BeautyOrder::getStatus, dto.getStatus())
                .like(StringUtils.checkValNotNull(dto.getId()), BeautyOrder::getId, dto.getId())
                .between(StringUtils.checkValNotNull(dto.getParams().get(Constants.BEGIN_TIME)), BeautyOrder::getGmtCreate, dto.getParams().get(Constants.BEGIN_TIME), dto.getParams().get(Constants.END_TIME));
    }
}
